/*
 * Copyright (C) 2006-2007 Eskil Bylund
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

using System;

using Gtk;

namespace DCSharp.Gui
{
	/// <summary>
	/// A PageManager that presents Pages in a Notebook.  
	/// </summary>
	public class PageManagerNotebook : PageManager
	{
		private Notebook notebook;

		#region Constructors

		public PageManagerNotebook() : base()
		{
#if GTK_2_10
			notebook = new Notebook();
#else
			notebook = new DragNotebook();
#endif
			notebook.EnablePopup = true;
			notebook.Scrollable = true;
			notebook.SwitchPage += OnSwitchPage;
			notebook.Show();

			Add(notebook);
		}

		#endregion

		#region Classes

		private class TabLabel : HBox
		{
			public EventHandler CloseButtonClicked;

			private Page page;

			private EventBox eventBox;
			private Image image;
			private Label label;
			private Button button;
			private Tooltips tooltips;
			private bool important;

			public TabLabel(Page page)
			{
				this.page = page;

				page.PageChanged += OnPageChanged;

				Spacing = 9;

				eventBox = new EventBox();
				eventBox.AboveChild = true;
				eventBox.VisibleWindow = false;
				Add(eventBox);

				HBox box = new HBox();
				box.Spacing = 3;
				eventBox.Add(box);

				image = new Image(page.Icon);
				box.PackStart(image, false, false, 0);

				label = new Label(page.Title);
				label.Xalign = 0;
				//label.Ellipsize = Pango.EllipsizeMode.End;
				box.Add(label);

				tooltips = new Tooltips();
				tooltips.SetTip(eventBox, page.Tooltip, page.Tooltip);

				Image closeImage = new Image();
				closeImage.SetFromStock(Stock.Close, IconSize.Menu);

				button = new Button(closeImage);
				button.Name = "dcsharp-close-button";
				button.Relief = ReliefStyle.None;
				button.FocusOnClick = false;
				button.SetSizeRequest(18, 18);
				button.Clicked += OnCloseButtonClicked;

				PackEnd(button, false, false, 0);

				ShowAll();
			}

			#region Properties

			public bool Important
			{
				get { return important; }
				set
				{
					important = value;

					if (important)
					{
						label.Markup = String.Format("<b>{0}</b>",
							GLib.Markup.EscapeText(page.Title));
					}
					else
					{
						label.Text = page.Title;
					}
				}
			}

			public bool CloseButtonVisible
			{
				get { return button.Visible; }
				set { button.Visible = value; }
			}

			#endregion

			#region Methods

			protected override void OnDestroyed()
			{
				page.PageChanged -= OnPageChanged;
				base.OnDestroyed();
			}

			protected override void OnStyleSet(Style previousStyle)
			{
				image.Pixbuf = page.Icon;
			}

			private void OnPageChanged(object obj, EventArgs args)
			{
				Important = important;
				image.Pixbuf = page.Icon;
				tooltips.SetTip(eventBox, page.Tooltip, page.Tooltip);
			}

			private void OnCloseButtonClicked(object obj, EventArgs args)
			{
				if (CloseButtonClicked != null)
				{
					CloseButtonClicked(this, EventArgs.Empty);
				}
			}

			#endregion
		}

		#endregion

		#region Properties

		public override int Count
		{
			get { return notebook.NPages; }
		}

		public override Page Current
		{
			get { return notebook.CurrentPageWidget as Page; }
		}

		public override Page this[int index]
		{
			get { return notebook.GetNthPage(index) as Page; }
		}

		#endregion

		#region Methods

		public override void Add(Page page)
		{
			// Create label
			TabLabel label = new TabLabel(page);
			label.CloseButtonClicked += delegate
			{
				Remove(page);
			};

			TabLabel menuLabel = new TabLabel(page);
			menuLabel.CloseButtonVisible = false;

			// Append
			page.BorderWidth = 6;
			notebook.AppendPageMenu(page, label, menuLabel);
#if GTK_2_10
			notebook.SetTabReorderable(page, true);
#endif
			page.PageChanged += OnPageChanged;
			page.Show();

			OnPageAdded(page);
		}

		public override void Remove(Page page)
		{
			int index = notebook.PageNum(page);
			if (index >= 0)
			{
				page.PageChanged -= OnPageChanged;

				notebook.RemovePage(index);
				OnPageRemoved(page);

				if (Count == 0)
				{
					OnCurrentPageChanged(null);
				}
			}
		}

		public override bool Contains(Page page)
		{
			foreach (Widget widget in notebook)
			{
				if (widget == page)
				{
					return true;
				}
			}
			return false;
		}

		public override void Present(Page page)
		{
			notebook.CurrentPage = notebook.PageNum(page);
		}

		private void SetTabLabelImportant(Page page, bool important)
		{
			TabLabel label = notebook.GetTabLabel(page) as TabLabel;
			if (label != null)
			{
				label.Important = important;
			}
		}

		private void OnSwitchPage(object obj, SwitchPageArgs args)
		{
			Page page = this[(int)args.PageNum];

			SetTabLabelImportant(page, false);

			// CurrentPageChanged is similar to SwitchPage but is also raised
			// when the last page is removed (CurrentPage == -1).
			OnCurrentPageChanged(page);
		}

		private void OnPageChanged(object obj, EventArgs args)
		{
			Page page = (Page)obj;
			if (page != Current)
			{
				SetTabLabelImportant(page, true);
			}
		}

		#endregion
	}
}
